/*
 * Copyright 2020 Espressif Systems (Shanghai) Co., Ltd.
 * All rights reserved.
 *
 * You may not use this file except in compliance with the terms and
 * conditions set forth in the accompanying LICENSE.TXT file.
 *
 * THESE MATERIALS ARE PROVIDED ON AN "AS IS" BASIS. ESPRESSIF/AMAZON SPECIFICALLY
 * DISCLAIMS, WITH RESPECT TO THESE MATERIALS, ALL WARRANTIES, EXPRESS,
 * IMPLIED, OR STATUTORY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
 */

#include <stdint.h>
#include <stddef.h>
#include <driver/flash.h>
#include <iot_flash.h>

IotFlashHandle_t iot_flash_open(int32_t lInstance){
    return (IotFlashHandle_t) 1;
}

int32_t iot_flash_close(IotFlashHandle_t const handle){
    return IOT_FLASH_SUCCESS;
}

IotFlashInfo_t *iot_flash_getinfo(IotFlashHandle_t const handle){
    if (NULL == handle) return NULL;

	static IotFlashInfo_t info;
    info.ulBlockSize = FLASH_BLOCK_SIZE;
    info.ulFlashSize = FLASH_CHIP_SIZE;
    info.ulLockSupportSize = FLASH_BLOCK_SIZE;
    info.ulSectorSize = FLASH_SECTOR_SIZE;
    info.ulPageSize = 256;
    info.ucAsyncSupported = 0;
    return &info;
}

void iot_flash_set_callback(IotFlashHandle_t const handle, IotFlashCallback_t cb, void *context){
    (void) handle; (void) cb; (void) context;
}

int32_t iot_flash_erase_sectors(IotFlashHandle_t const handle, uint32_t addr, size_t len){
    if (NULL == handle) return IOT_FLASH_INVALID_VALUE;

    if ((addr % FLASH_SECTOR_SIZE) != 0 || (len % FLASH_SECTOR_SIZE) != 0) {
        return IOT_FLASH_INVALID_VALUE;
    }

    int ret = flash_erase_range(addr, len);
    return ret ? IOT_FLASH_ERASE_FAILED : IOT_FLASH_SUCCESS ;
}

int32_t iot_flash_erase_chip(IotFlashHandle_t const handle){
    if (NULL == handle) return IOT_FLASH_INVALID_VALUE;

    int ret = flash_erase_chip();
    return ret ? IOT_FLASH_ERASE_FAILED : IOT_FLASH_SUCCESS ;
}

int32_t iot_flash_write_sync(IotFlashHandle_t const handle, uint32_t addr, uint8_t *const buff, size_t len){
    if (NULL == handle || (int) addr < 0 || NULL == buff ) {
        return IOT_FLASH_INVALID_VALUE;
    }
    int ret = flash_write(addr, buff, len);
    return ret ? IOT_FLASH_WRITE_FAILED : IOT_FLASH_SUCCESS;

}

int32_t iot_flash_read_sync(IotFlashHandle_t const handle, uint32_t addr, uint8_t *const buff, size_t len){
    if (NULL == handle || (int) addr < 0 || NULL == buff) {
        return IOT_FLASH_INVALID_VALUE;
    }

    int ret = flash_read(addr, buff, len);
    return ret ? IOT_FLASH_READ_FAILED : IOT_FLASH_SUCCESS;
}

int32_t iot_flash_ioctl(IotFlashHandle_t const handle, int req, void *const buff){
    if (NULL == handle || (volatile int) req < 0) {
        return IOT_FLASH_INVALID_VALUE;
    }
    return IOT_FLASH_FUNCTION_NOT_SUPPORTED;
}

